/*
 * JVM_Opcode.c
 *
 *  Created on: 04.01.2011
 *      Author: Tavin
 */

#include <stdint.h>


#include "JVM_StackFrame.h"

#include "JVM_StatusCodes.h"

#include "JVM_Opcode.h"

#include "JVM_OpcodeArray.h"

#include "JVM_OpcodeBranch.h"

#include "JVM_OpcodeCompare.h"
#include "JVM_OpcodeConstant.h"
#include "JVM_OpcodeConvert.h"

#include "JVM_OpcodeException.h"

#include "JVM_OpcodeFields.h"

#include "JVM_OpcodeInvoke.h"
#include "JVM_OpcodeInstance.h"

#include "JVM_OpcodeLoad.h"
#include "JVM_OpcodeLogic.h"

#include "JVM_OpcodeMath.h"

#include "JVM_OpcodeReference.h"

#include "JVM_OpcodeStore.h"
#include "JVM_OpcodeStack.h"

#include "JVM_Thread.h"
#include "JVM_ClassTable.h"
#include "Console.h"


uint16_t (* JVM_OpcodeTable [0xca]) ()={
		JVM_cmd_nop, 		 	    		// cmd_nop 						0x00
		JVM_cmd_aconst_null,			// cmd_aconst_null  	0x01

		JVM_cmd_iconst_m1, 				// cmd_iconst_m1 			0x02

		JVM_cmd_iconst_0, 				// cmd_iconst_0 			0x03
		JVM_cmd_iconst_1, 				// cmd_iconst_1				0x04
		JVM_cmd_iconst_2, 				// cmd_iconst_2 	 		0x05
		JVM_cmd_iconst_3, 				// cmd_iconst_3				0x06
		JVM_cmd_iconst_4, 				// cmd_iconst_4 			0x07
		JVM_cmd_iconst_5, 				// cmd_iconst_5 			0x08

		JVM_cmd_lconst_0, 				// cmd_lconst_0				0x09
		JVM_cmd_lconst_1, 				// cmd_lconst_1 			0x0a

		JVM_cmd_fconst_0, 				// cmd_fconst_0 			0x0b
		JVM_cmd_fconst_1, 				// cmd_fconst_1 			0x0c
		JVM_cmd_fconst_2,		  		// cmd_fconst_2 			0x0d

		JVM_cmd_dconst_0, 				// cmd_dconst_0 			0x0e
		JVM_cmd_dconst_1, 				// cmd_dconst_1				0x0f


		JV_cmd_bipush, 						// cmd_bipush 				0x10

		JV_cmd_sipush, 						// cmd_sipush 				0x11

		JVM_cmd_ldc, 							// cmd_ldc 						0x12
		JVM_cmd_ldc_w, 						// cmd_ldc_w					0x13

		JVM_cmd_ldc2_w,		 				// cmd_ldc2_w					0x14

		JVM_cmd_iload, 						// cmd_iload					0x15
		JVM_cmd_lload, 						// cmd_lload 					0x16
		JVM_cmd_iload, 						// cmd_fload					0x17
		JVM_cmd_lload, 						// cmd_dload					0x18

		JVM_cmd_aload, 						// cmd_aload 					0x19

		JVM_cmd_iload_0, 					// cmd_iload_0 				0x1a
		JVM_cmd_iload_1, 					// cmd_iload_1 				0x1b
		JVM_cmd_iload_2, 					// cmd_iload_2 				0x1c
		JVM_cmd_iload_3, 					// cmd_iload_3 				0x1d


		JVM_cmd_lload_0, 					// cmd_lload_0				0x1e
		JVM_cmd_lload_1, 					// cmd_lload_1				0x1f
		JVM_cmd_lload_2, 					// cmd_lload_2 				0x20
		JVM_cmd_lload_3,	 				// cmd_lload_3 				0x21

		JVM_cmd_iload_0, 					// cmd_fload_0 				0x22
		JVM_cmd_iload_1, 					// cmd_fload_1 				0x23
		JVM_cmd_iload_2, 					// cmd_fload_2 				0x24
		JVM_cmd_iload_3,					// cmd_fload_3 				0x25

		JVM_cmd_lload_0, 					// cmd_dload_0 				0x26
		JVM_cmd_lload_1, 					// cmd_dload_1	 			0x27
		JVM_cmd_lload_2, 					// cmd_dload_2 				0x28
		JVM_cmd_lload_3, 					// cmd_dload_3 				0x29


		JVM_cmd_aload_0, 					// cmd_aload_0				0x2a
		JVM_cmd_aload_1, 					// cmd_aload_1 				0x2b
		JVM_cmd_aload_2, 					// cmd_aload_2 				0x2c
		JVM_cmd_aload_3, 					// cmd_aload_3 				0x2d

		JVM_cmd_iaload, 					// cmd_iaload 				0x2e
		JVM_cmd_laload, 					// cmd_laload 				0x2f
		JVM_cmd_faload,	 					// cmd_faload 				0x30
		JVM_cmd_daload, 					// cmd_daload 				0x31
		JVM_cmd_aaload, 					// cmd_aaload 				0x32
		JVM_cmd_baload, 					// cmd_baload					0x33
		JVM_cmd_caload, 					// cmd_caload 				0x34
		JVM_cmd_saload, 					// cmd_saload 				0x35

		JVM_cmd_istore, 					// cmd_istore 				0x36
		JVM_cmd_lstore, 					// cmd_lstore 				0x37
		JVM_cmd_fstore, 					// cmd_fstore 				0x38
		JVM_cmd_dstore, 					// cmd_dstore 				0x39
		JVM_cmd_astore, 					// cmd_astore 				0x3a

		JVM_cmd_istore_0, 				// cmd_istore_0 			0x3b
		JVM_cmd_istore_1, 				// cmd_istore_1 			0x3c
		JVM_cmd_istore_2, 				// cmd_istore_2 			0x3d
		JVM_cmd_istore_3, 				// cmd_istore_3 			0x3e

		JVM_cmd_lstore_0, 				// cmd_lstore_0				0x3f
		JVM_cmd_lstore_1, 				// cmd_lstore_1		 		0x40
		JVM_cmd_lstore_2,					// cmd_lstore_2				0x41
		JVM_cmd_lstore_3, 				// cmd_lstore_3				0x42

		JVM_cmd_fstore_0, 				// cmd_fstore_0				0x43
		JVM_cmd_fstore_1, 				// cmd_fstore_1				0x44
		JVM_cmd_fstore_2, 				// cmd_fstore_2				0x45
		JVM_cmd_fstore_3, 				// cmd_fstore_3				0x46

		JVM_cmd_dstore_0, 				// cmd_dstore_0 			0x47
		JVM_cmd_dstore_1, 				// cmd_dstore_1 			0x48
		JVM_cmd_dstore_2, 				// cmd_dstore_2 			0x49
		JVM_cmd_dstore_3, 				// cmd_dstore_3 			0x4a

		JVM_cmd_astore_0, 				// cmd_astore_0 			0x4b
		JVM_cmd_astore_1, 				// cmd_astore_1 			0x4c
		JVM_cmd_astore_2, 				// cmd_astore_2 			0x4d
		JVM_cmd_astore_3, 				// cmd_astore_3 			0x4e

		JVM_cmd_iastore, 					// cmd_iastore 				0x4f
		JVM_cmd_lastore, 					// cmd_lastore 				0x50
		JVM_cmd_fastore, 					// cmd_fastore 				0x51
		JVM_cmd_dastore, 					// cmd_dastore 				0x52
		JVM_cmd_aastore,					// cmd_aastore 				0x53
		JVM_cmd_bastore,					// cmd_bastore	 			0x54
		JVM_cmd_castore, 					// cmd_castore 				0x55
		JVM_cmd_sastore, 					// cmd_sastore 				0x56

		JVM_cmd_pop, 							// cmd_pop 						0x57
		JVM_cmd_pop2,							// cmd_pop2 					0x58

		JVM_cmd_dup, 							// cmd_dup 						0x59
		JVM_cmd_dup_x1, 					// cmd_dup_x1					0x5a
		JVM_cmd_dup_x2, 					// cmd_dup_x2 				0x5b

		JVM_cmd_dup2, 						// cmd_dup2 					0x5c
		JVM_cmd_dup2_x1, 					// cmd_dup2_x1 				0x5d
		JVM_cmd_dup2_x2, 					// cmd_dup2_x2 				0x5e

		JVM_cmd_swap, 						// cmd_swap 					0x5f

		JVM_cmd_iadd, 						// cmd_iadd 					0x60
		JVM_cmd_ladd, 						// cmd_ladd 					0x61
		JVM_cmd_fadd, 						// cmd_fadd 					0x62
		JVM_cmd_dadd, 						// cmd_dadd 					0x63

		JVM_cmd_isub, 						// cmd_isub 					0x64
		JVM_cmd_lsub, 						// cmd_lsub 					0x65
		JVM_cmd_fsub, 						// cmd_fsub 					0x66
		JVM_cmd_dsub, 						// cmd_dsub 					0x67

		JVM_cmd_imul, 						// cmd_imul 					0x68
		JVM_cmd_lmul, 						// cmd_lmul						0x69
		JVM_cmd_fmul, 						// cmd_fmul 					0x6a
		JVM_cmd_dmul, 						// cmd_dmul 					0x6b

		JVM_cmd_idiv, 						// cmd_idiv 					0x6c
		JVM_cmd_ldiv, 						// cmd_ldiv 					0x6d
		JVM_cmd_fdiv, 						// cmd_fdiv 					0x6e
		JVM_cmd_ddiv, 						// cmd_ddiv 					0x6f

		JVM_cmd_irem, 						// cmd_irem 					0x70
		JVM_cmd_lrem, 						// cmd_lrem 					0x71
		0, 												// cmd_frem 					0x72
		0, 												// cmd_drem						0x73

		JVM_cmd_ineg, 						// cmd_ineg 					0x74
		JVM_cmd_lneg, 						// cmd_lneg 					0x75
		JVM_cmd_fneg, 						// cmd_fneg 					0x76
		JVM_cmd_dneg,							// cmd_dneg 					0x77

		JVM_cmd_ishl, 						// cmd_ishl 					0x78
		JVM_cmd_lshl, 						// cmd_lshl 					0x79

		JVM_cmd_ishr, 						// cmd_ishr 					0x7a
		JVM_cmd_lshr, 						// cmd_lshr 					0x7b

		JVM_cmd_iushr, 						// cmd_iushr 					0x7c
		JVM_cmd_lushr, 						// cmd_lushr 					0x7d

		JVM_cmd_iand, 						// cmd_iand 					0x7e
		JVM_cmd_land, 						// cmd_land 					0x7f

		JVM_cmd_ior, 							// cmd_ior 						0x80
		JVM_cmd_lor, 							// cmd_lor 						0x81

		JVM_cmd_ixor, 						// cmd_ixor 					0x82
		JVM_cmd_lxor, 						// cmd_lxor 					0x83

		JVM_cmd_iinc, 						// cmd_iinc 					0x84

		JVM_cmd_i2l, 							// cmd_i2l 						0x85
		JVM_cmd_i2f, 							// cmd_i2f						0x86
		JVM_cmd_i2d, 							// cmd_i2d 						0x87

		JVM_cmd_l2i, 							// cmd_l2i 						0x88
		JVM_cmd_l2f, 							// cmd_l2f 						0x89
		JVM_cmd_l2d, 							// cmd_l2d 						0x8a

		JVM_cmd_f2i, 							// cmd_f2i 						0x8b
		JVM_cmd_f2l, 							// cmd_f2l 						0x8c
		JVM_cmd_f2d, 							// cmd_f2d 						0x8d

		JVM_cmd_d2i, 							// cmd_d2i 						0x8e
		JVM_cmd_d2l, 							// cmd_d2l 						0x8f
		JVM_cmd_d2f, 							// cmd_d2f 						0x90

		JVM_cmd_i2b, 							// cmd_i2b 						0x91
		JVM_cmd_i2c, 							// cmd_i2c 						0x92
		JVM_cmd_i2s, 							// cmd_i2s 						0x93

		JVM_cmd_lcmp, 						// cmd_lcmp	 					0x94
		JVM_cmd_fcmpl, 						// cmd_fcmpl 					0x95
		JVM_cmd_fcmpg, 						// cmd_fcmpg 					0x96
		JVM_cmd_dcmpl,				 		// cmd_dcmpl 					0x97
		JVM_cmd_dcmpg, 						// cmd_dcmpg 					0x98

		JVM_cmd_ifeq, 						// cmd_ifeq 					0x99
		JVM_cmd_ifne,	 						// cmd_ifne 					0x9a
		JVM_cmd_iflt, 						// cmd_iflt 					0x9b
		JVM_cmd_ifge, 						// cmd_ifge 					0x9c
		JVM_cmd_ifgt, 						// cmd_ifgt 					0x9d
		JVM_cmd_ifle, 						// cmd_ifle 					0x9e

		JVM_cmd_if_icmpeq, 				// cmd_if_icmpeq 			0x9f
		JVM_cmd_if_icmpne, 				// cmd_if_icmpne 			0xa0
		JVM_cmd_if_icmplt, 				// cmd_if_icmplt 			0xa1
		JVM_cmd_if_icmpge, 				// cmd_if_icmpge 			0xa2


		JVM_cmd_if_icmpgt, 				// cmd_if_icmpgt 			0xa3
		JVM_cmd_if_icmple, 				// cmd_if_icmple 			0xa4
		JVM_cmd_if_acmpeq, 				// cmd_if_acmpeq 			0xa5
		JVM_cmd_if_acmpne, 				// cmd_if_acmpne 			0xa6

		JVM_cmd_goto, 						// cmd_goto 					0xa7

		JVM_cmd_jsr, 							// cmd_jsr 						0xa8
		JVM_cmd_ret, 							// cmd_ret 						0xa9

		JVM_cmd_tableswitch, 			// cmd_tableswitch 		0xaa
		JVM_cmd_lookupswitch, 		// cmd_lookupswitch 	0xab

		JVM_cmd_ireturn, 					// cmd_ireturn 				0xac
		JVM_cmd_lreturn, 					// cmd_lreturn 				0xad
		JVM_cmd_freturn, 					// cmd_freturn 				0xae
		JVM_cmd_dreturn, 					// cmd_dreturn 				0xaf
		JVM_cmd_areturn, 					// cmd_areturn 				0xb0
		JVM_cmd_return,				 		// cmd_return 				0xb1

		JVM_cmd_getstatic, 				// cmd_getstatic 			0xb2
		JVM_cmd_putstatic, 				// cmd_putstatic 			0xb3

		JVM_cmd_getfield, 				// cmd_getfield 			0xb4
		JVM_cmd_putfield, 				// cmd_putfield 			0xb5

		JVM_cmd_invokevirtual,	 	// cmd_invokevirtual 	0xb6
		JVM_cmd_invokespecial,		// cmd_invokespecial 	0xb7
		JVM_cmd_invokestatic, 		// cmd_invokestatic 	0xb8
		0, 												// cmd_invokeinterface 0xb9

		0, 												// cmd_xxxunusedxxx1 	0xba
		JVM_cmd_new, 							// cmd_new 						0xbb

		JVM_cmd_newarray, 				// cmd_newarray 			0xbc
		JVM_cmd_anewarray, 				// cmd_anewarray 			0xbd
		JVM_cmd_arraylength, 			// cmd_arraylength 		0xbe

		JVM_cmd_athrow, 					// cmd_athrow 				0xbf

		0, 												// cmd_checkcast 			0xc0

		0, 												// cmd_instanceof 		0xc1

		0, 												// cmd_monitorenter 	0xc2
		0, 												// cmd_monitorexit 		0xc3

		0, 												// cmd_wide 					0xc4

		JVM_cmd_multianewarray, 	// cmd_multianewarray 0xc5

		JVM_cmd_ifnull, 					// cmd_ifnull 				0xc6
		JVM_cmd_ifnonnull, 				// cmd_ifnonnull 			0xc7

		0, 												// cmd_goto_w 				0xc8

		0}; 											// cmd_jsr_w 					0xc9


uint16_t JVM_Opcode_execute()
{
	uint8_t opcode;
	uint16_t StatusCode;

	opcode=JVM_Opcode_getCodeByte();//activeStackFrame->currentMethod->code[activeStackFrame->PC++];
	StatusCode=JVM_OpcodeTable[opcode] ();

	// Handle Exception
	switch (StatusCode) {
		case STCD_EXCEPTION:
			// TODO: exception
			break;
		case STCD_NULL_REFERENCE:
			// TODO: null reference exception
			break;
		case STCD_ARITHMETIC_EXCEPTION:
			// no try catch finally block
			// print exception type
			Console_putChar('A');

			JVM_Class_t *exceptionClass = JVM_ClassTable_get(JAVA_LANG_ARITHMETICEXCEPTION_INDEX);
			uint8_t *data =  exceptionClass->constantPoolTable->constants[1]->data;

			//exceptionClass->constantPoolTable->constants[1]->size
			//for (i = 0; i < 29; i++) {
			data+=2;
		  while (*(data) != '\0') {
				Console_putCharWait(*(data));
				data++;
			}
			//}


				JVM_Stack_unroll(activeThread->currentStackframe);
			return STCD_THREAD_DESTROY;
			break;
		case STCD_OUT_OF_BOUNDS_EXCEPTION:
			// TODO: OUT OF BOUNDS
			break;
		default: // no exception
			return(StatusCode);
	}

	return(StatusCode);
}

